package edu.hawaii.ics314.ical.model;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.text.ParseException;
import java.util.Objects;


/**
 * The TimeZone class defines what a time zone is
 * including its name, ID, and where it offsets to
 * and from.
 * 
 * @author 
 *
 */
public class TimeZone extends CalendarComponent {
		
	private Property<String> name;
	private Property<String> id;
	private Property<String> offsetFrom;
	private Property<String> offsetTo;
	
	private boolean isDaylightSavingTime;
	
	// DEVDOC: For deserialization purposes only.
	public TimeZone(CalendarComponentInfo info) {
		super(info);
	}
	
	/**
	 * Constructor that creates a new <code>Timezone</code>.
	 * 
	 * @param name - the name.
	 * @param id - the unique identification value.
	 * @param offsetFrom - the amount of time it is offset from.
	 * @param offsetTo - the amount of time it is offset to.
	 * @param isDaylightSavingTime - whether is it Daylight Savings Time or not.
	 * @param info - extra calendar components being added.
	 */
	public TimeZone(Property<String> name, Property<String> id, Property<String> offsetFrom, 
			Property<String> offsetTo, boolean isDaylightSavingTime, CalendarComponentInfo info) {
		super(info);
		this.name = Objects.requireNonNull(name);
		this.id = Objects.requireNonNull(id);
		this.isDaylightSavingTime = isDaylightSavingTime;
		this.offsetFrom = Objects.requireNonNull(offsetFrom);
		this.offsetTo = Objects.requireNonNull(offsetTo);
	}
	
	/**
	 * Returns the name of <code>Timezone</code>.
	 * 
	 * @return The name of <code>Timezone</code>.
	 */
	public String getName() {
		return name.getValue();
	}
	
	/**
	 * Returns the ID of <code>Timezone</code>.
	 * 
	 * @return The ID of <code>Timezone</code>.
	 */
	public String getID() {
		return id.getValue();
	}
	
	/**
	 * Returns whether it is Daylight Savings Time or not.
	 * 
	 * @return Whether it is Daylight Savings Time or not.
	 */
	public boolean isDaylightSavingTime() {
		return isDaylightSavingTime;
	}
	
	/**
	 * Returns the offset from <code>Timezone</code>.
	 * 
	 * @return The offset from <code>Timezone</code>.
	 */
	public String getOffsetFrom() {
		return offsetFrom.getValue();
	}
	
	/**
	 * Returns the offset to <code>Timezone</code>.
	 * 
	 * @return The offset to <code>Timezone</code>.
	 */
	public String getOffsetTo() {
		return offsetTo.getValue();
	}
	
	@Override
	public String toString() {
		return "TZID:" + id.VALUE + "\r\n";
	}

	@Override
	public void readObject(BufferedReader in) throws IOException, ParseException {
		String curLine = null;
		do {
			curLine = peekNextLine(in);
			if(curLine.equals("BEGIN:VTIMEZONE") || curLine.equals("END:STANDARD") 
					|| curLine.equals("END:DAYLIGHT")) {
				in.readLine(); // Commit the read and ignore line.
			} else if(curLine.equals("END:VTIMEZONE")) {
				in.readLine(); // Commit the read and return control to caller.
				break;
			} else if(curLine.equals("BEGIN:DAYLIGHT") || curLine.equals("BEGIN:STANDARD")) {
				in.readLine(); // Commit the read and return control to caller.
				isDaylightSavingTime = curLine.equals("BEGIN:DAYLIGHT");
			} else {
				// Do NOT commit the read. Begin parsing standard properties.
				readProperties(in, new PropertyRecognizer() {

					@Override
					public boolean isRecognized(Property<String> property) throws ParseException {
						switch(property.getName()) {
						case "TZNAME":
							name = property;
							return true;
						case "TZID":
							id = property;
							return true;
						case "OFFSETFROM":
							offsetFrom = property;
							return true;
						case "OFFSETTO":
							offsetTo = property;
							return true;
						default:
							return false;
						}
					}
					
				});
			}
		} while(curLine != null);
	}

	@Override
	public void writeObject(BufferedWriter out) throws IOException {
		final String CRLF = "\r\n";
		out.write("BEGIN:VTIMEZONE");
		out.write(CRLF);
		out.write(id.toString());
		out.write("BEGIN:" + (isDaylightSavingTime ? "DAYLIGHT" : "STANDARD"));
		out.write(CRLF);
		writeProperties(out);
		if(name != null) {
			out.write(name.toString());
		}
		if(offsetFrom != null) {
			out.write(offsetFrom.toString());
		}
		if(offsetTo != null) {
			out.write(offsetTo.toString());
		}
		out.write("END:" + (isDaylightSavingTime ? "DAYLIGHT" : "STANDARD"));
		out.write(CRLF);
		out.write("END:VTIMEZONE");
	}
	
	@Override
	public boolean equals(Object other) {
		if(other instanceof TimeZone) {
			TimeZone tzOther = (TimeZone) other;
			return getName().equals(tzOther.getName()) && getID().equals(tzOther.getID()) 
					&& getOffsetFrom().equals(tzOther.getOffsetFrom()) && getOffsetTo().equals(tzOther.getOffsetTo());
		} else {
			return false;
		}
	}

}
